package cn.asiontang.utils;

import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.util.Log;

import java.io.File;

public final class ImageUtils
{
    private static final String TAG = "ImageUtils";

    /**
     * <p>
     * 【当原图的最长边<b> 小于等于</b>maxSize时,直接返回原bitmap】
     * </p>
     * 封装了系统默认的
     * {@link android.graphics.Bitmap#createScaledBitmap(Bitmap, int, int, boolean)}
     * 函数，具备了自动按最大边计算<b>等比缩放</b>后的最小边功能。<br>
     * <br>
     * 计算最长边的缩放比，得到等比缩放后的新大小。 例如：原图1024*768 ，新图要求以最大边为准缩放为320的，则
     *
     * <pre>
     * 最小边可计算为 = (320/1024=0.3125) * 768 = 240；
     * </pre>
     *
     * @param bitmap        原图，调用此函数后，可能会被自动recycle();！
     * @param maxSize       新图的最大边的大小
     * @param enableEnlarge 是否允许将原图放大.<br/>
     *                      true:传递过来的原图bitmap最长边小于maxSize时,扩大至maxSize,然后返回新图bitmap
     *                      原Bitmap【会】被自动销毁。<br/>
     *                      false:传递过来的原图bitmap最长边小于maxSize时,直接返回原图bitmap
     * @return 1.出现任何异常都将被吞掉并 返回Null，而 原Bitmap【不会】被自动销毁。
     */
    public static final Bitmap getResizedImage(final Bitmap bitmap, final int maxSize, final boolean enableEnlarge)
    {
        if (bitmap == null)
            return null;
        try
        {
            int w = bitmap.getWidth();
            int h = bitmap.getHeight();

            // 计算最长边的缩放比，得到等比缩放后的新大小。
            // 例如：原图1024*768 ，新图要求以最大边为准缩放为320的，则
            //  最小边可计算为 = (320/1024=0.3125) * 768 =  240；
            if (h > w)
            {
                if (!enableEnlarge && maxSize >= h)
                    return bitmap;
                w = (int) (w * ((double) maxSize / h));
                h = maxSize;
            } else
            {
                if (!enableEnlarge && maxSize >= w)
                    return bitmap;
                h = (int) (h * ((double) maxSize / w));
                w = maxSize;
            }

            //filter true if the source should be filtered.可以增加质量？
            final Bitmap b = Bitmap.createScaledBitmap(bitmap, w, h, true);
            //其实 createScaledBitmap 已经出问题了，没有压缩成功，所以返回了Null值。
            if (b == null)
                return null;

            //因为Bitmap.createBitmap可能会返回原对象，所以要判断不是时，才能销毁原对象。
            if (b != bitmap)
                recycleQuietly(bitmap);
            return b;
        } catch (final Exception ex)
        {
            Log.e(TAG, "getResizedImage(bitmap,  maxSize, enableEnlarge)", ex);
            return null;
        }
    }

    /**
     * 求最优重采样率值（inSampleSize）
     *
     * @param w                       原图宽
     * @param h                       原图高
     * @param targetMaxSize           “目标图”期望的最长边大小 【当异常情况下，传入的“目标尺寸”有误时，直接返回 4】
     * @param allowSmallerThanMaxSize 当不允许“实际图”尺寸小于“目标图”尺寸时，直接返回缩放比为【最优解】
     * @author AsionTang
     */
    private static final int getSmartSampleSize(final int w, final int h, final int targetMaxSize, final boolean allowSmallerThanMaxSize)
    {
        //当异常情况下，传入的“目标尺寸”有误时，直接返回 4
        if (targetMaxSize <= 0)
            return 4;

        final int originalMaxSize = Math.max(w, h);
        final int scale = originalMaxSize / targetMaxSize;
        //当目标尺寸 大于 原图尺寸时，直接返回1.
        if (scale == 0 || scale == 1)
            return 1;

        //当不允许“实际图”尺寸小于“目标图”尺寸时，直接返回缩放比为【最优解】
        if (!allowSmallerThanMaxSize)
            return scale;

        //获取系统默认时，输出的图片大小
        final int systemSampleSize = getSystemInSampleSize(scale);
        final int systemOutputSize = originalMaxSize / systemSampleSize;
        final int diff = Math.abs(targetMaxSize - systemOutputSize);
        //当和“目标图”尺寸完全一致时，就可直接返回了。
        if (diff == 0)
            return systemSampleSize;

        //获取内存占用尽量小时，输出的图片大小
        final int nextSystemSampleSize = getSystemInSampleSize(systemSampleSize + 1);
        final int nextSystemOutputSize = originalMaxSize / nextSystemSampleSize;
        final int nextDiff = Math.abs(targetMaxSize - nextSystemOutputSize);
        //当和“目标图”尺寸完全一致时，就可直接返回了。
        if (nextDiff == 0)
            return nextSystemSampleSize;

        //比对，相差目标尺寸，哪种相差更小，就取哪种重采样值（sampleSize）
        if (nextDiff < diff)
            return nextSystemSampleSize;
        if (nextDiff > diff)
            return systemSampleSize;

        //当前两种差别都一样时，则根据系统是否在“低内存”状态，来取尽可能小的内存占用。
        if (MemoryUtils.isInLowMemory())//nextDiff == diff
            return nextSystemSampleSize;
        else
            return systemSampleSize;
    }

    private static final int getSystemInSampleSize(final int b)
    {
        if (b >= 8)
            return (b / 8) * 8;
        else if (b >= 4)
            return 4;
        else if (b >= 2)
            return 2;
        return 1;
    }

    public static final void recycleQuietly(final Bitmap b)
    {
        if (b == null || b.isRecycled())
            return;
        try
        {
            b.recycle();
        } catch (final Exception ignore)
        {
            ignore.printStackTrace();
        }
    }

    public static final void recycleQuietly(final Drawable b)
    {
        if (b == null || !(b instanceof BitmapDrawable))
            return;
        recycleQuietly(((BitmapDrawable) b).getBitmap());
    }

    public static final void showImageBySystemDefaultApp(final Context context, final String path)
    {
        try
        {
            final Intent intent = new Intent();
            intent.setAction(Intent.ACTION_VIEW);
            intent.setDataAndType(Uri.fromFile(new File(path)), "image/*");
            context.startActivity(intent);
        } catch (final ActivityNotFoundException ignore)
        {
            ToastEx.makeTextAndShowLong("系统找不到合适的APP打开此图片！");
        } catch (final Exception ignore)
        {
            ignore.printStackTrace();
        }
    }
}